#include "board.h"
#include "myfunctions.h"
Board::Board() {
	stalemate = false;
	whiteKingMoved = false;
	whiteRRookMoved = false;
	whiteLRookMoved = false;
	blackKingMoved = false;
	blackRRookMoved = false;
	blackLRookMoved = false;
	lastWasDoublePawn = false;
	willDoCastle = false;
	canDoEnPassant = false;
	lastDoublePawn = Cell(123,123);
}
void Board::setView(IChessView *view) {
	myView = view;
}
Board::~Board() {
	removeAllPieces();
}
void Board::PlaceAllPieces() {
	std::vector<ChessPiece *>::iterator it;
	for ( it=piecesOnBoard.begin() ; it < piecesOnBoard.end(); it++ ) {
		ChessPiece * p = *it;
		p->setBoard(this);
		PlacePiece(p);
	}
}
void Board::PlacePiece(ChessPiece * piece) {
	myView->PlacePiece(piece->row,piece->col,piece->image);
}
void Board::StartBoard() {
}
ChessPiece * Board::getPieceAt(int row , int col) {
	std::vector<ChessPiece *>::iterator it;
	for ( it = piecesOnBoard.begin() ; it < piecesOnBoard.end() ; it++) {
		ChessPiece*p = *it;
		if(p->row == row && p->col == col) {
			return p;
		}
	}
	return NULL;
}
int Board::getPiecePosAt(int row , int col) {
	for( int i = 0 ; i < piecesOnBoard.size() ; i++) {
		ChessPiece * p = piecesOnBoard[i];
		if(p->col == col && p->row ==row) {
			return i;
		}
	}
	return 200;
}
void Board::KillPiece(int row , int col) {
	myView->ClearPiece(row,col);
	ChessPiece * p = getPieceAt(row,col);
	delete p;
	piecesOnBoard.erase(piecesOnBoard.begin()+getPiecePosAt(row,col));
}
void Board::movePiece(int row , int col , int endrow , int endcol) {
	bool isKill = false;
	if(getPiecePosAt(endrow,endcol)!=200) {
		//myView->WriteMessageArea("will Kill something.\n");
		KillPiece(endrow,endcol);
		isKill = true;
	}
	ChessPiece * toMove = getPieceAt(row,col);
	toMove->setCell(endrow,endcol);
	myView->ClearPiece(row,col);
	myView->PlacePiece(endrow,endcol,toMove->image);
}
void Board::moveTestPiece(int row , int col , int endrow , int endcol) {
	bool isKill = false;
	if(getPiecePosAt(endrow,endcol)!=200) {
		//myView->WriteMessageArea("will Kill something.\n");
		KillPiece(endrow,endcol);
		isKill = true;
	}
	ChessPiece * toMove = getPieceAt(row,col);
	toMove->setCell(endrow,endcol);
}
void Board::highlightCell(int row, int col) {
	myView->HighlightSquare(row,col,BLUE_SQUARE);
}
void Board::unhighlightCell(Cell c) {
	myView->UnHighlightSquare(c.row,c.col);
}
void Board::unhighlightAll() {
	for ( int row = 0; row <= 7 ; row++) {
		for ( int col = 0 ; col <=7 ; col++) {
			myView->UnHighlightSquare(row,col);
		}
	}
}
void Board::removeAllPieces() {
	std::vector<ChessPiece *>::iterator it;
	for ( it=piecesOnBoard.begin() ; it < piecesOnBoard.end(); it++ ) {
		ChessPiece * p = *it;
		delete p;
	}
	piecesOnBoard.clear();
}
void Board::ClearAllPieces() {
	for( int row = 0 ; row <= 7 ; row++) {
		for ( int col = 0 ; col <= 7 ; col++) {
			myView->ClearPiece(row,col);
		}
	}
}
bool Board::hasEnemy(Color attacker, int row, int col) {
	ChessPiece * p = getPieceAt(row,col);
	if(p!=NULL) {
		Color enemy = p->pColor;
		if(attacker == white) {
			return enemy == black;
		}
		if(attacker == black) {
			return enemy == white;
		}
	}
	return false;
}
bool Board::hasTeamate(Color attacker, int row, int col) {
	ChessPiece * p = getPieceAt(row,col);
	if(p!=NULL) {
		Color enemy = p->pColor;
		return enemy == attacker;
	}
	return false;
}
bool Board::hasAnyPiece(int row, int col) {
	ChessPiece * p = getPieceAt(row,col);
	if(p!=NULL) {
		return true;
	}
	return false;
}
Cell Board::findKing(Color color) {
	std::vector<ChessPiece*>::iterator it;
	for ( it = piecesOnBoard.begin() ; it < piecesOnBoard.end() ; it++) {
		ChessPiece * p2 = *it;
		if(p2->pColor == color) {
			if(p2->image == W_KING || p2->image == B_KING) {
				return Cell(p2->row , p2->col);
			}
		}
	}
}
Cell Board::findEnemyKing(ChessPiece * p) {
	std::vector<ChessPiece*>::iterator it;
	for ( it = piecesOnBoard.begin() ; it < piecesOnBoard.end() ; it++) {
		ChessPiece * p2 = *it;
		if(p2->pColor != p->pColor) {
			if(p2->image == W_KING || p2->image == B_KING) {
				return Cell(p2->row , p2->col);
			}
		}
	}
}
Cell Board::findTeamKing(ChessPiece * p) {
	std::vector<ChessPiece*>::iterator it;
	for ( it = piecesOnBoard.begin() ; it < piecesOnBoard.end() ; it++) {
		ChessPiece * p2 = *it;
		if(p2->pColor == p->pColor) {
			if(p2->image == W_KING || p2->image == B_KING) {
				return Cell(p2->row , p2->col);
			}
		}
	}
}
ChessPiece * Board::getStartPiece(Move m) {
	std::string type = m.startType;
	Color newCor = white;
	if(m.color == "black")
		newCor = black;
	if(type == "pawn") {
		return new Pawn(m.startRowint,m.startColint,newCor);
	}
	if(type == "king") {
		return new King(m.startRowint,m.startColint,newCor);
	}
	if(type == "queen") {
		return new Queen(m.startRowint,m.startColint,newCor);
	}
	if(type == "bishop") {
		return new Bishop(m.startRowint,m.startColint,newCor);
	}
	if(type == "knight") {
		return new Knight(m.startRowint,m.startColint,newCor);
	}
	return new Rook(m.startRowint,m.startColint,newCor);
}
ChessPiece * Board::getKillPiece(Move m) {
	std::string type = m.killType;
	Color newCor = white;
	if(m.color == "white")
		newCor = black;
	if(type == "pawn") {
		return new Pawn(m.endRowint,m.endColint,newCor);
	}
	if(type == "king") {
		return new King(m.endRowint,m.endColint,newCor);
	}
	if(type == "queen") {
		return new Queen(m.endRowint,m.endColint,newCor);
	}
	if(type == "bishop") {
		return new Bishop(m.endRowint,m.endColint,newCor);
	}
	if(type == "knight") {
		return new Knight(m.endRowint,m.endColint,newCor);
	}
	return new Rook(m.endRowint,m.endColint,newCor);
}
void Board::UnPawnPro(Move m) {
	KillPiece(m.startRowint,m.startColint);
	ChessPiece * toAdd = getStartPiece(m);
	toAdd->setBoard(this);
	piecesOnBoard.push_back(toAdd);
	PlacePiece(toAdd);
}
void Board::UnCastle(Move m) {
	if(m.endRowint == 0) {
		blackKingMoved = false;
		if(m.endColint == 2) {
			KillPiece(0,3);
			ChessPiece * p = new Rook(0,0,black);
			p->setBoard(this);
			piecesOnBoard.push_back(p);
			PlacePiece(p);
			blackLRookMoved = false;
		}
		if(m.endColint == 6) {
			KillPiece(0,5);
			ChessPiece * p = new Rook(0,7,black);
			p->setBoard(this);
			piecesOnBoard.push_back(p);
			PlacePiece(p);
			blackRRookMoved = false;
		}
	}
	if(m.endRowint == 7) {
		whiteKingMoved = false;
		if(m.endColint == 2) {
			KillPiece(7,3);
			ChessPiece * p = new Rook(7,0,white);
			p->setBoard(this);
			piecesOnBoard.push_back(p);
			PlacePiece(p);
			whiteLRookMoved = false;
		}
		if(m.endColint == 6) {
			KillPiece(7,5);
			ChessPiece * p = new Rook(7,7,white);
			p->setBoard(this);
			piecesOnBoard.push_back(p);
			PlacePiece(p);
			whiteRRookMoved = false;
		}
	}
}
bool Board::undoOneMove() {
	Move lastMove = moveHistory.back();
	//move piece back
	ChessPiece * initialmove = getPieceAt(lastMove.endRowint,lastMove.endColint);
	initialmove->setCell(lastMove.startRowint,lastMove.startColint);
	//show move piece back
	myView->ClearPiece(lastMove.endRowint,lastMove.endColint);
	PlacePiece(initialmove);
	if(lastMove.PawnPro) {
		UnPawnPro(lastMove);
	}
	if(lastMove.castle) {
		UnCastle(lastMove);
	}
	if(lastMove.enPassant) {
		Color passantColor = (lastMove.color == "white") ? black : white;
		int add = (lastMove.color == "black") ? -1 : 1;
		ChessPiece * p = new Pawn(lastMove.PassantRow + add,lastMove.endColint,passantColor);
		p->setBoard(this);
		piecesOnBoard.push_back(p);
		PlacePiece(p);
		lastWasDoublePawn = true;
		lastDoublePawn = Cell(p->row,p->col);
	}
	if(lastMove.kill) {
		Color kColor = (lastMove.color == "white") ? black : white;
		ChessPiece * p = getKillPiece(lastMove);
		p->setBoard(this);
		piecesOnBoard.push_back(p);
		PlacePiece(p);
	}
	moveHistory.erase(moveHistory.end());
	return true;
}
std::string Board::printMoveHistory() {
	std::vector<Move>::iterator it;
	for ( it = moveHistory.begin() ; it < moveHistory.end() ; it++) {
		Move m = *it;
		myView->WriteMessageArea("\nStart move:\n\ttype:");
		myView->WriteMessageArea(m.startType + "\n\tcolor:");
		myView->WriteMessageArea(m.color + "\n\tcol:");
		myView->WriteMessageArea(m.startCol + "\n\trow:");
		myView->WriteMessageArea(m.startRow);
		myView->WriteMessageArea("\nEnd move:\n\ttype:");
		myView->WriteMessageArea(m.endType + "\n\tcolor:");
		myView->WriteMessageArea(m.color + "\n\tcol:");
		myView->WriteMessageArea(m.endCol + "\n\trow:");
		myView->WriteMessageArea(m.endRow);
		if(m.kill) {
			myView->WriteMessageArea("\nKill move:\n\ttype:");
			myView->WriteMessageArea(m.killType + "\n\tcolor:");
			myView->WriteMessageArea((m.color == "white") ? "black" : "white");
			myView->WriteMessageArea(m.startCol + "\n\trow:");
			myView->WriteMessageArea(m.startRow);
		}
	}
}
void Board::checkLoadedCastleMoves() {
	std::vector<Move>::iterator it;
	for ( it = moveHistory.begin() ; it < moveHistory.end() ; it++) {
		Move m = *it;
		if(m.castle) {
			whiteKingMoved == (m.color == "white" || whiteKingMoved) ? true : false;
			blackKingMoved == (m.color == "black" || blackKingMoved) ? true : false;
		}
		if(m.startType == "rook") {
			whiteRRookMoved = ( m.startRowint == 7 && m.startColint == 7
			                    || whiteRRookMoved) ? true : false;
			whiteLRookMoved = ( m.startRowint == 7 && m.startColint == 0
			                    || whiteLRookMoved) ? true : false;
			blackRRookMoved = ( m.startRowint == 0 && m.startColint == 7
			                    || blackRRookMoved) ? true : false;
			blackLRookMoved = ( m.startRowint == 0 && m.startColint == 0
			                    || blackLRookMoved) ? true : false;
		}
		if(m.endType == "rook") {
			whiteRRookMoved = ( m.endRowint == 7 && m.endColint == 7
			                    || whiteRRookMoved) ? true : false;
			whiteLRookMoved = ( m.endRowint == 7 && m.endColint == 0
			                    || whiteLRookMoved) ? true : false;
			blackRRookMoved = ( m.endRowint == 0 && m.endColint == 7
			                    || blackRRookMoved) ? true : false;
			blackLRookMoved = ( m.endRowint == 0 && m.endColint == 0
			                    || blackLRookMoved) ? true : false;
		}
		if(m.startType == "king") {
			whiteKingMoved = (m.color == "white" || whiteKingMoved) ? true : false;
			blackKingMoved = (m.color == "black" || blackKingMoved) ? true : false;
		}
	}
}
void Board::checkLastWasDoublepawn() {
	Move m = moveHistory.back();
	if(m.startType == "pawn") {
		int sub = m.startRowint - m.endRowint;
		if(sub == 2 || sub == -2) {
			lastDoublePawn = Cell(m.endRowint,m.endColint);
			this->lastWasDoublePawn = true;
		}
	}
}
